#include <iostream>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <cstring>

using namespace std;

int main()
{
  // 创建套接字
  int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
  if (listen_sock < 0){
    cerr << "socket creat fail" << endl;
    exit(1);
  }
  cout << "socket creat succes, socket: " << listen_sock << endl;
  int opt = 1;
  setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  // 绑定
  struct sockaddr_in local;

  memset(&local, 0, sizeof(local));

  local.sin_family = AF_INET;
  local.sin_port = htons(8081);
  local.sin_addr.s_addr = INADDR_ANY;

  
  if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
    cerr << "bind fail" << endl;
    exit(2);
  }
  cout << "bind success" << endl;

  // 将套接字设置为监听状态
  if (listen(listen_sock, 5) < 0){
    cerr << "listen fail" << endl;
    exit(3);
  }
  
  struct sockaddr_in peer;
  socklen_t len = sizeof(peer);
  while (1){
    // 获取连接
    int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
    if (sock < 0){
      cerr << "accept error" << endl;
      continue;
    }
    
    // 创建子进程
    if (fork() == 0){
      close(listen_sock);
      if (fork() > 0){
        exit(-1);
      }
      else{
        // 孙子进程
        while (1){
          char buf[1024];
          ssize_t size = recv(sock, buf, sizeof(buf), 0);
          
          if (size >  0){
            buf[size] = 0;

            cout << "#################################### http begin ############################################" << endl;
            cout << buf << endl;
            cout << "#################################### http   end ############################################" << endl;
            
            // 响应
            int fd = open("index1.html", O_RDONLY);
            struct stat st;
            stat("./index1.html", &st);
              
            //string status_line = "HTTP/1.1 307 Temporary Redirect";
            string status_line = "HTTP/1.1 200 OK\n";
            // 2.响应报头
            string response_header = "Content-Length: " + to_string(st.st_size) + "\n";
            response_header += "Content-Type: text/html\n";
            //response_header += "Set-Cookie: ;\n";
            //response_header += "location: https://www.qq.com\n";
            // 3.空行
            string blank = "\n";
            // 4.正文
            
            send(sock, status_line.c_str(), status_line.size(), 0);
            send(sock, response_header.c_str(), response_header.size(), 0);
            send(sock, blank.c_str(), blank.size(), 0); 
            
            sendfile(sock, fd, nullptr, st.st_size);
            close(fd);
          }
          else if (size == 0){
            cout << "close" << endl;
            break;
          }
          else{
            cerr << "recv error" << endl;
          }
        }

        close(sock);
        exit(0);
      }
    }

    close(sock);
    waitpid(-1, nullptr, 0);
  }
  return 0;
}
